/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var zrUtil = require("static/plugins/js/zrender/lib/core/util");

var Region = require("./Region");

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * Parse and decode geo json
 * @module echarts/coord/geo/parseGeoJson
 */
function decode(json) {
    if (!json.UTF8Encoding) {
        return json;
    }

    var encodeScale = json.UTF8Scale;

    if (encodeScale == null) {
        encodeScale = 1024;
    }

    var features = json.features;

    for (var f = 0; f < features.length; f++) {
        var feature = features[f];
        var geometry = feature.geometry;
        var coordinates = geometry.coordinates;
        var encodeOffsets = geometry.encodeOffsets;

        for (var c = 0; c < coordinates.length; c++) {
            var coordinate = coordinates[c];

            if (geometry.type === "Polygon") {
                coordinates[c] = decodePolygon(
                    coordinate,
                    encodeOffsets[c],
                    encodeScale
                );
            } else if (geometry.type === "MultiPolygon") {
                for (var c2 = 0; c2 < coordinate.length; c2++) {
                    var polygon = coordinate[c2];
                    coordinate[c2] = decodePolygon(
                        polygon,
                        encodeOffsets[c][c2],
                        encodeScale
                    );
                }
            }
        }
    } // Has been decoded

    json.UTF8Encoding = false;
    return json;
}

function decodePolygon(coordinate, encodeOffsets, encodeScale) {
    var result = [];
    var prevX = encodeOffsets[0];
    var prevY = encodeOffsets[1];

    for (var i = 0; i < coordinate.length; i += 2) {
        var x = coordinate.charCodeAt(i) - 64;
        var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding

        x = (x >> 1) ^ -(x & 1);
        y = (y >> 1) ^ -(y & 1); // Delta deocding

        x += prevX;
        y += prevY;
        prevX = x;
        prevY = y; // Dequantize

        result.push([x / encodeScale, y / encodeScale]);
    }

    return result;
}
/**
 * @alias module:echarts/coord/geo/parseGeoJson
 * @param {Object} geoJson
 * @return {module:zrender/container/Group}
 */

function _default(geoJson) {
    decode(geoJson);
    return zrUtil.map(
        zrUtil.filter(geoJson.features, function (featureObj) {
            // Output of mapshaper may have geometry null
            return (
                featureObj.geometry &&
                featureObj.properties &&
                featureObj.geometry.coordinates.length > 0
            );
        }),
        function (featureObj) {
            var properties = featureObj.properties;
            var geo = featureObj.geometry;
            var coordinates = geo.coordinates;
            var geometries = [];

            if (geo.type === "Polygon") {
                geometries.push({
                    type: "polygon",
                    // According to the GeoJSON specification.
                    // First must be exterior, and the rest are all interior(holes).
                    exterior: coordinates[0],
                    interiors: coordinates.slice(1),
                });
            }

            if (geo.type === "MultiPolygon") {
                zrUtil.each(coordinates, function (item) {
                    if (item[0]) {
                        geometries.push({
                            type: "polygon",
                            exterior: item[0],
                            interiors: item.slice(1),
                        });
                    }
                });
            }

            var region = new Region(properties.name, geometries, properties.cp);
            region.properties = properties;
            return region;
        }
    );
}

module.exports = _default;
